import 'package:built_collection/built_collection.dart';
import 'package:equatable/equatable.dart';
import 'package:mobile_app.core/core/domain/entities/dialect.dart';
import 'package:mobile_app.core/core/domain/entities/settings/image_settings.dart';
import 'package:mobile_app.core/core/domain/entities/learning_content/lexical_item/lexical_item.dart';
import 'package:mobile_app.core/core/domain/entities/learning_info/learning_info.dart';
import 'package:mobile_app.core/core/domain/entities/settings/learning_settings.dart';
import 'package:mobile_app.core/core/domain/helpers/handle_learning_activity/helper.dart';
import 'package:mobile_app.core/core/domain/services/image_service/service.dart';
import 'package:mobile_app.home.learning.training/training_page/domain/entities/card_info/card_info.dart';
import 'package:mobile_app.home.learning.training/training_page/domain/entities/training_exercise.dart';
import 'package:mobile_app.home.learning.training/training_page/domain/entities/training_history_item.dart';
import 'package:mobile_app.home.learning.training/training_page/domain/helpers/create_exercise_card_info/helper.dart';
import 'package:mobile_app.home.learning.training/training_page/domain/helpers/get_training_progress/helper.dart';
import 'package:mobile_app.home.learning.training/training_page/domain/helpers/handle_training_completion/helper.dart';
import 'package:mobile_app.home.learning.training/training_page/domain/helpers/pick_next_exercise/helper.dart';

part 'result.dart';

abstract class HandleTranslationSelectionCardCompletion {
  TranslationSelectionCardCompletionHandlingResult call({
    required TranslationSelectionCardInfo currentCardInfo,
    required BuiltList<TrainingHistoryItem> trainingHistory,
    required BuiltSet<TrainingExercise> exercises,
    required LearningSettings learningSettings,
    required ImageSettings imageSettings,
    required BuiltMap<String, LexicalItem> trainingLexicalItemMap,
    required BuiltMap<String, LexicalItem> lexicalItemMap,
    required LearningInfo learningInfo,
    required BuiltList<DateTime> appReviewRequestTimes,
    required Dialect dialect,
    required BuiltMap<Dialect, BuiltSet<String>> unsafeToPronounceLexicalItemTitleMap,
  });
}

class HandleTranslationSelectionCardCompletionImpl
    implements HandleTranslationSelectionCardCompletion {
  const HandleTranslationSelectionCardCompletionImpl({
    required CreateExerciseCardInfo createExerciseCardInfo,
    required GetTrainingProgress getTrainingProgress,
    required PickNextExercise pickNextExercise,
    required ImageService imageService,
    required HandleLearningActivity handleLearningActivity,
    required HandleTrainingCompletion handleTrainingCompletion,
  })  : _createExerciseCardInfo = createExerciseCardInfo,
        _getTrainingProgress = getTrainingProgress,
        _pickNextExercise = pickNextExercise,
        _imageService = imageService,
        _handleLearningActivity = handleLearningActivity,
        _handleTrainingCompletion = handleTrainingCompletion;

  final CreateExerciseCardInfo _createExerciseCardInfo;
  final GetTrainingProgress _getTrainingProgress;
  final PickNextExercise _pickNextExercise;
  final ImageService _imageService;
  final HandleLearningActivity _handleLearningActivity;
  final HandleTrainingCompletion _handleTrainingCompletion;

  @override
  TranslationSelectionCardCompletionHandlingResult call({
    required TranslationSelectionCardInfo currentCardInfo,
    required BuiltList<TrainingHistoryItem> trainingHistory,
    required BuiltSet<TrainingExercise> exercises,
    required LearningSettings learningSettings,
    required ImageSettings imageSettings,
    required BuiltMap<String, LexicalItem> trainingLexicalItemMap,
    required BuiltMap<String, LexicalItem> lexicalItemMap,
    required LearningInfo learningInfo,
    required BuiltList<DateTime> appReviewRequestTimes,
    required Dialect dialect,
    required BuiltMap<Dialect, BuiltSet<String>> unsafeToPronounceLexicalItemTitleMap,
  }) {
    final updatedLearningInfo = _handleLearningActivity(
      learningInfo: learningInfo,
    );

    final updatedTrainingHistory = trainingHistory.rebuild((trainingHistory) {
      final trainingHistoryItem = TrainingHistoryItem(
        exercise: TrainingExercise.translationSelection,
        lexicalItemId: currentCardInfo.lexicalItem.id,
        successful: true,
      );

      trainingHistory.add(trainingHistoryItem);
    });

    final trainingLexicalItemIds = trainingLexicalItemMap.keys.toBuiltSet();

    final progress = _getTrainingProgress(
      trainingHistory: updatedTrainingHistory,
      exerciseCount: exercises.length,
      lexcialItemCount: trainingLexicalItemIds.length,
    );

    final nextExercisePickingResult = _pickNextExercise(
      trainingLexicalItemIds: trainingLexicalItemIds,
      trainingHistory: updatedTrainingHistory,
      exercises: exercises,
      exerciseShuffleEnablementEffective:
          learningSettings.trainingSettings.exerciseShuffleEnablementEffective,
    );

    if (nextExercisePickingResult == null) {
      final trainingCompletionHandlingResult = _handleTrainingCompletion(
        trainingLexicalItemMap: trainingLexicalItemMap,
        lexicalItemMap: lexicalItemMap,
        learningInfo: updatedLearningInfo,
        appReviewRequestTimes: appReviewRequestTimes,
      );

      final nextCardInfo = SummarizingCardInfo(
        lexicalItems: trainingCompletionHandlingResult.trainedLexicalItems,
        lexicalItemProgressPercentMap:
            trainingCompletionHandlingResult.trainedLexicalItemProgressPercentMap,
      );

      final result = CompletedTrainingTranslationSelectionCardCompletionHandlingResult(
        currentCardInfo: nextCardInfo,
        previousCardInfo: currentCardInfo,
        trainingHistory: updatedTrainingHistory,
        progress: progress,
        lexicalItemMap: trainingCompletionHandlingResult.lexicalItemMap,
        appReviewRequestTimes: trainingCompletionHandlingResult.appReviewRequestTimes,
        appReviewRequestReasonable: trainingCompletionHandlingResult.appReviewRequestReasonable,
        learningInfo: updatedLearningInfo,
      );

      return result;
    }

    final nextCardInfo = _createExerciseCardInfo(
      exercise: nextExercisePickingResult.exercise,
      trainingLexicalItemId: nextExercisePickingResult.lexicalItemId,
      trainingLexicalItemMap: trainingLexicalItemMap,
      dialect: dialect,
      unsafeToPronounceLexicalItemTitleMap: unsafeToPronounceLexicalItemTitleMap,
      cachedImagePathMap: _imageService.cachedImagePathMap,
      imageSettings: imageSettings,
      lexicalItemMap: lexicalItemMap,
    );

    final result = OngoingTrainingTranslationSelectionCardCompletionHandlingResult(
      currentCardInfo: nextCardInfo,
      previousCardInfo: currentCardInfo,
      trainingHistory: updatedTrainingHistory,
      progress: progress,
      learningInfo: updatedLearningInfo,
    );

    return result;
  }
}
